#include "XSystem/XCore.h"

XUserInterface::XUserInterface(XResourcesManager *data)
{
	x_data = data;
	x_clickedLastFrame = false;
}

// Add a window to the window manager
void XUserInterface::AddWindow(XWindow *window, std::string windowName)
{
	x_windows[windowName] = window;
	x_windowsOrder.push_back(windowName);
}

// /return the current screen name
std::string XUserInterface::screen()
{
	return x_screen;
}

// Set the current screen
void XUserInterface::SetScreen(std::string screenName)
{
	if (screenName != x_screen)
	{
		std::cout << "New screen : " << screenName << std::endl;

		std::string tempScreen;
		std::vector<std::string> tempScreens;
		std::string screenList = x_screens[screenName];
		int lastCheck = 0;
		int checkPosition = 0;
		bool done = false;

		// Put the screen names in a vector
		while (lastCheck < screenList.size()-1)
		{
			// Check for the variable value
			done = false;
			while (!done)
			{
				if (screenList[checkPosition] == ';')
				{
					tempScreen = screenList.substr(lastCheck,  (checkPosition - lastCheck));
					done = true;
					lastCheck = checkPosition + 1;
				}

				checkPosition++;
			}

			tempScreens.push_back(tempScreen);
		}

		// Open/close windows if necessary
		for(std::map<std::string, XWindow*>::const_iterator it = x_windows.begin(); it != x_windows.end(); ++it)
		{
			bool found = false;
			for (int i=0; i<tempScreens.size(); i++)
				// If on the screen list, open the window
				if (tempScreens[i] == it->first)
				{
					x_windows[it->first]->SetVisible(true);
					found = true;
				}

			// If not on the screen list, close the window
			if (!found)
				x_windows[it->first]->SetVisible(false);
		}
	}
}

// Add a new screen 
void XUserInterface::AddScreen(std::string screenName, std::string windows)
{
	x_screens[screenName] = windows;
}

// Check the states of the windows (and widgets) : mouse position, clicking...
void XUserInterface::CheckState(const sf::Input &input)
{
	if (x_windows.size() > 0)
	{
		std::string currentWindow = x_windowsOrder[x_windowsOrder.size() - 1];
		std::string nextWindowSelected = "";
		int nextWindowPosBefore = 0;

		// Check widgets state
		bool canCheck = true;
		bool isOnTopOfAWindow = false;
		for (int i=0; i<x_windowsOrder.size(); i++)
		{
			x_windows[x_windowsOrder[x_windowsOrder.size() - i - 1]]->CheckQuery();

			if (x_windows[x_windowsOrder[x_windowsOrder.size() - i - 1]]->CheckPosition(input.GetMouseX(), input.GetMouseY()))
			{
				if (x_windows[x_windowsOrder[x_windowsOrder.size() - i - 1]]->isStatic() && x_data->GetInt("movingWindow") == 1)
					canCheck = false;

				if (canCheck)
					x_windows[x_windowsOrder[x_windowsOrder.size() - i - 1]]->CheckState(input);

				nextWindowSelected = x_windowsOrder[x_windowsOrder.size() - i - 1]; 
				nextWindowPosBefore = x_windowsOrder.size() - i - 1;

				isOnTopOfAWindow = true;
				break;
			}
		}
		if (!isOnTopOfAWindow)
			x_windows[x_windowsOrder[x_windowsOrder.size() - 1]]->CheckState(input);

		// If clicked somewhere, check if clicked on a different window
		if (input.IsMouseButtonDown(sf::Mouse::Left))
		{
			if (!x_clickedLastFrame)
			{
				// Not the same window
				if (nextWindowSelected != "")
				{
					// If not clicking on the same window as last click, change window order.
					if (nextWindowSelected != currentWindow)
					{
						if (!x_windows[nextWindowSelected]->isStatic())
						{
							x_windowsOrder.erase(x_windowsOrder.begin() + nextWindowPosBefore);
							x_windowsOrder.push_back(nextWindowSelected);
						}
					}
				} 

				x_clickedLastFrame = true;

			} else {

				x_windows[x_windowsOrder[x_windowsOrder.size() - 1]]->DragWindow(input.GetMouseX(), input.GetMouseY());

				x_clickedLastFrame = true;
			}

		// Reset dragging
		} else {

			x_clickedLastFrame = false;

			for (int i=0; i<x_windows.size(); i++)
				x_windows[x_windowsOrder[i]]->ResetDrag();

			x_data->SetInt("movingWindow", 0);
		}
	}
}

// Check the events of the windows (and widgets) : key pressed
void XUserInterface::CheckEvent(const sf::Event &Event)
{
	if (x_windows.size() > 0)
	{
		for (int i=0; i<x_windows.size(); i++)
		{
			if (x_windows[x_windowsOrder[x_windowsOrder.size() - 1 - i]]->visible())
			{
				if (!x_windows[x_windowsOrder[x_windowsOrder.size() - 1 - i]]->isStatic())
					x_windows[x_windowsOrder[x_windowsOrder.size() - 1 - i]]->CheckEvent(Event);
				break;
			}
		}

		// Events of the static windows
		for (int i=0; i<x_windows.size(); i++)
		{
			if (x_windows[x_windowsOrder[x_windowsOrder.size() - 1 - i]]->visible())
			{
				if (x_windows[x_windowsOrder[x_windowsOrder.size() - 1 - i]]->isStatic())
					x_windows[x_windowsOrder[x_windowsOrder.size() - 1 - i]]->CheckEvent(Event);
			}
		}
	}
}

// Check the functions of the ui
void XUserInterface::CheckFunctions()
{
	if (!x_data->queueEmpty("ui"))
	{
		functions function = x_data->nextQueue("ui");

		if (function.argument == "setscreen")
			SetScreen(function.variable);
		else if (function.argument == "displaywindow")
			x_windows[function.variable]->SetVisible(true);

		// If the popup window is showing, put it on top
		if (function.variable == "popup")
		{
			int position = 0;
			for (int i=0; i<x_windowsOrder.size(); i++)
				if (x_windowsOrder[i] == "popup")
					position = i;

			x_windowsOrder.erase(x_windowsOrder.begin() + position);
			x_windowsOrder.push_back("popup");
		}
	}
}

// Draws the windows
void XUserInterface::Draw()
{
	for (int i=0; i<x_windowsOrder.size(); i++)
		x_windows[x_windowsOrder[i]]->Draw();
}
